#include "book_management.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Book *book_head=0;// the head node of allbooks
static Book *book_last=0;
static BookArray *allbooks=0;// the list of allbooks
static int book_number=0;// the number of added books to generate unique id

//saves the database of books in the specified file
//returns 0 if books were stored correctly, or an error code otherwise
int store_books()
{
	FILE *fp;
	fp = fopen("books.txt", "w+");
	if (!fp) {
		fprintf(stderr, "Failed in opening %s\n", "books.txt");
		return -1;
	}
	if(book_number != 0){
	fprintf(fp, "Total number of books:%d\n", allbooks->length);
	Book *current;
	for(current=allbooks->array->next;current;current=current->next){
		fprintf(fp, "id:%d\n", current->id);
		fprintf(fp, "title:%s\n", current->title);
		fprintf(fp, "authors:%s\n", current->authors);
		fprintf(fp, "year:%d\n", current->year);
		fprintf(fp, "copies:%d\n", current->copies);
		fprintf(fp, "loan:%d\n", current->loan);
	}
	fclose(fp);
	Book *temp;
	current=book_head;
	while(!current){
		temp=current;
		current=current->next;
		free(temp);
	}
	free(allbooks);
	}
	return 0;
}

//loads the database of books from the specified file
//the file must have been generated by a previous call to store_books()
//returns 0 if books were loaded correctly, or an error code otherwise
int load_books()
{
	FILE *fp;
	char buf[70];
	int nbook=0;
 	fp = fopen("books.txt", "r");
	if (!fp){
		fprintf(stderr, "Error in opening books.txt\n");
		return -1;
	}

    //Read the first line
    if (fgets(buf, 70, fp) != NULL){
		sscanf(buf, "Total number of books:%d\n", &nbook);
        allbooks=(BookArray*)malloc(sizeof(BookArray));
		allbooks->length=nbook;

		//Read in book entries
		int id,year,copies,loan;
		char title[70],authors[70];
		book_head=(Book*)malloc(sizeof(Book));
		book_last=book_head;
   	 	for(int i=0;i<nbook;i++){
     	   //Load book id
			fgets(buf, 70, fp);
			sscanf(buf,"id:%d\n", &id);
			//Load book title, authors
			fgets(buf, 70, fp);
			sscanf(buf, "title:%s\n", title);
			fgets(buf, 70, fp);
			sscanf(buf, "authors:%s\n", authors);
			//Load year,copies,loan
			fgets(buf, 70, fp);
			sscanf(buf,"year:%d\n", &year);
			fgets(buf, 70, fp);
			sscanf(buf,"copies:%d\n", &copies);
			fgets(buf, 70, fp);
			sscanf(buf, "loan:%d\n", &loan);

			// create node
			Book *node=(Book*)malloc(sizeof(Book));
			node->id=id;
			node->title=(char*)malloc(sizeof(strlen(title)));
			strcpy(node->title,title);
			node->authors=(char*)malloc(sizeof(strlen(authors)));
			strcpy(node->authors,authors);
			node->year=year;
			node->copies=copies;
			node->loan=loan;
			book_last->next=node;
			book_last=node;
   		}
		book_last->next=NULL;
		allbooks->array=(Book*)malloc(sizeof(Book));
		allbooks->array=book_head;
		book_number=book_last->id;
		fclose(fp);
		return 0;
	}
}

//adds a book to the ones available to the library
//returns 0 if the book could be added, or an error code otherwise
int add_book(Book book)
{
	//add copies if books have exit
	if(book_number!=0){
	Book *current;
	for(current=book_head->next;current;current=current->next){
		if(!strcmp(current->title,book.title)&&!strcmp(current->authors,book.authors)&&current->year==book.year){
			current->copies=current->copies+book.copies;
			if(book.loan!=0){
				current->loan = current->loan - 1;
			}
			printf("Book was successfully added.\n");
			return 0;
		}
	}
	}
	
	//get new book
	Book *new_book = (Book *)malloc(sizeof(Book));
	new_book->title = (char *)malloc(sizeof(strlen(book.title)));
	strcpy(new_book->title,book.title);
	new_book->authors = (char *)malloc(sizeof(strlen(book.authors)));
	strcpy(new_book->authors,book.authors);
	new_book->year = book.year;
	new_book->copies = book.copies;
	new_book->id = book_number+1;
	new_book->loan=0;

	//add new book
	if(book_number==0){//no book before
		book_head=(Book *)malloc(sizeof(Book));
		book_last=book_head;
		book_last->next=new_book;
		book_last=new_book;
		book_last->next=NULL;
		allbooks=(BookArray *)malloc(sizeof(BookArray));
		allbooks->array=(Book *)malloc(sizeof(Book));
		allbooks->array=book_head;
		allbooks->length=0;
	}else{// have books
		book_last->next=new_book;
		book_last=new_book;
		book_last->next=NULL;
	}
	book_number++;
	allbooks->length++;
	printf("Book was successfully added.\n");
	return 0;
}

//removes a book from the library
//returns 0 if the book could be successfully removed, or an error code otherwise.
int remove_book(int id)
{
	Book *current;
	Book *temp;
	for(current=book_head;current->next;current=current->next){
		if(current->next->id==id){
			if(current->next->loan==0){
				temp=current->next;
				current->next=temp->next;
				free(temp);
				printf("Remove successfully.\n");
				return 0;
			}else{
				printf("Someone borrowed this book. Remove unseccessfully.\n");
				return 1;
			}
		}
	}
	printf("Please enter valid id.\n");
	return 1;
}

//finds books with a given title.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the 
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
BookArray find_book_by_title (const char *title)
{
	Book *current,*temp;
	Book *head=0,*last=0;
	BookArray bookarray;
	int count=0;
	if(allbooks){
	for(current=book_head->next;current;current=current->next){
		if(current->title){
			if(strstr(current->title,title)){
				if(count==0){
					head=(Book *)malloc(sizeof(Book));
					last=head;
				}
				temp=(Book*)malloc(sizeof(Book));
				temp->id=current->id;
				temp->title=current->title;
				temp->authors=current->authors;
				temp->year=current->year;
				temp->copies=current->copies;
				temp->loan=current->loan;

				last->next=temp;
				last=temp;
				count++;
			}
		}
	}
	last->next=NULL;
	bookarray.array=head;
	}
	bookarray.length=count;
	return bookarray;
}

//finds books with the given authors.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the 
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
BookArray find_book_by_author (const char *author)
{
	Book *current,*temp;
	Book *head=0,*last=0;
	BookArray bookarray;
	int count=0;
	if(allbooks){
	for(current=book_head->next;current;current=current->next){
	if(current->authors){
		if(strstr(current->authors,author)){
			if(count==0){
				head=(Book *)malloc(sizeof(Book));
				last=head;
			}
			temp=(Book*)malloc(sizeof(Book));
			temp->id=current->id;
			temp->title=current->title;
			temp->authors=current->authors;
			temp->year=current->year;
			temp->copies=current->copies;
			temp->loan=current->loan;
			last->next=temp;
			last=temp;
			count++;
		}
	}
	}
	last->next=NULL;
	bookarray.array=head;
	}
	bookarray.length=count;
	return bookarray;
}

//finds books published in the given year.
//returns a BookArray structure, where the field "array" is a newly allocated array of books, or null if no book with the 
//provided title can be found. The length of the array is also recorded in the returned structure, with 0 in case
//array is the null pointer.
BookArray find_book_by_year (unsigned int year)
{
	Book *current,*temp;
	Book *head=0,*last=0;
	BookArray bookarray;
	int count=0;
	if(allbooks){
	for(current=book_head->next;current;current=current->next){
		if(current->year==year){
			if(count==0){
				head=(Book *)malloc(sizeof(Book));
				last=head;
			}
			temp=(Book*)malloc(sizeof(Book));
			temp->id=current->id;
			temp->title=current->title;
			temp->authors=current->authors;
			temp->year=current->year;
			temp->copies=current->copies;
			temp->loan=current->loan;
			last->next=temp;
			last=temp;
			count++;
		}
	}
	last->next=NULL;
	bookarray.array=head;
	}
	bookarray.length=count;
	return bookarray;
}

//diaplay all books from bookarray
void display_books(BookArray bookarray)
{
	Book *current;
	if(bookarray.length==0){
		printf("No books found.\n");
		return;
	}else{

	// title
	printf("\n%-*s",4,"Id");
	printf("%-*s",20,"Title");
	printf("%-*s",18,"Authors");
	printf("%-*s",8,"Year");
	printf("%-*s\n",8,"Copies");
	
	// data
	for(current = bookarray.array->next;current;current=current->next){
		printf("%-4d", current->id);
		printf("%-*s",20, current->title);
		printf("%-*s",18, current->authors);
		printf("%-8d%-8d\n", current->year, current->copies);
	}
	}
}

void display_allbooks(){
	if(allbooks)
		display_books(*allbooks);
	else
		printf("No books\n");
}
